package com.rtsapp.server.domain.support;

import com.rtsapp.server.bytecode.ClassGenerator;
import com.rtsapp.server.domain.Dao;
import com.rtsapp.server.domain.DaoBuilder;
import com.rtsapp.server.domain.mysql.sql.MySQLResultSetHandler;
import com.rtsapp.server.domain.support.jpa.ColumnDef;
import com.rtsapp.server.domain.support.jpa.TableDef;
import com.rtsapp.server.logger.Logger;
import com.rtsapp.server.utils.ReflectUtils;
import com.rtsapp.server.utils.ReflectionUtils;
import com.rtsapp.server.utils.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;

/**
 * Created by admin on 15-9-19.
 * 针对Mysql实现方式的
 */
public class MysqlDaoBuilder extends DaoBuilder {

    private static final Logger log = com.rtsapp.server.logger.LoggerFactory.getLogger(MysqlDaoBuilder.class);

    private static final String INSERT = "insert";
    private static final String UPDATE = "update";
    private static final String DELETE = "delete";

    private static final String DIRECT_INSERT = "direct_insert";
    private static final String DIRECT_UPDATE = "direct_update";
    private static final String DIRECT_DELETE = "direct_delete";


    private static final String GETALL = "getAll";
    private static final String GET = "get";
    private static final String UPDATE_FOR = "update_";

    private static final String GET_BY = "getBy_";


    private static final String NEW_LINE = System.lineSeparator();


    @Override
    public StringBuilder getDaoCode(Class<? extends Dao> daoClass, String queueKey) {

        StringBuilder classDebug = new StringBuilder();

        createDaoImplClassOrGenCode(daoClass, classDebug, false, queueKey);

        return classDebug;
    }


    private Class<?> createDaoImplClassOrGenCode(Class<? extends Dao> daoClass, StringBuilder classDebug, boolean toClass, String queueKey) {
        //1. 获得实体类型
        ParameterizedType daoType = (ParameterizedType) daoClass.getGenericSuperclass();
        Class entityClass = (Class) daoType.getActualTypeArguments()[0];
        Class idClass = (Class) daoType.getActualTypeArguments()[1];

        //2. 解析获得持久化的表名 和所有所有持久化属性
        TableDef table = JpaUtils.getTableDef(entityClass);

        //3.构造类和方法

        ClassGenerator handlerCG = createResultHandlerClass(classDebug, daoClass, entityClass, idClass, table);
        ClassGenerator daoCG = createDaoImplClass0(classDebug, daoClass, entityClass, idClass, table, queueKey);

        Class<?> returnDaoClass = null;
        if (toClass) {
            handlerCG.toClass();
            returnDaoClass = daoCG.toClass();
        }

        return returnDaoClass;
    }

    private ClassGenerator createResultHandlerClass(StringBuilder classDebug, Class<? extends Dao> daoClass, Class entityClass, Class idClass, TableDef table) {

        ClassGenerator cg = ClassGenerator.newInstance();
        cg.importPackage("java.sql");
        cg.importPackage("java.util");
        cg.importPackage("com.rtsapp.server.domain.mysql.sql");
        cg.importPackage("com.rtsapp.server.domain");
        cg.importPackage(entityClass.getPackage().getName());

        String className = getResultHandlerName(daoClass);
        cg.setClassName(className);
        cg.addInterface(MySQLResultSetHandler.class);

        String field = "    List entityList = new ArrayList();" + NEW_LINE + NEW_LINE;
        cg.addField(field);

        String fieldSetter = "    public List getEntityList(){" + NEW_LINE +
                "        return entityList;" + NEW_LINE +
                "    }" + NEW_LINE + NEW_LINE;
        cg.addMethod(fieldSetter);

        StringBuilder sb = new StringBuilder();
        sb.append("    @SuppressWarnings(\"deprecation\")" + NEW_LINE);
        sb.append("    public void doResultSet(ResultSet rs) {" + NEW_LINE +
                "        try {\n" +
                "            while (rs.next()) {" + NEW_LINE +
                "                " + entityClass.getName() + " entity = EntityBuilder.newEntity(" + entityClass.getName() + ".class);" + NEW_LINE);

        createGetOnEntityCode(table, sb);

        sb.append("                entity.clearDirty();" + NEW_LINE);
        sb.append("                entityList.add(entity);" + NEW_LINE +
                "            }\n" +
                "        } catch (SQLException e) {" + NEW_LINE +
                "            e.printStackTrace();" + NEW_LINE +
                "        }\n" +
                "    }" + NEW_LINE);

        cg.addMethod(sb.toString());
        cg.addDefaultConstructor();

        classDebug.append("class " + getResultHandlerSimpleName(daoClass) + " implements MySQLResultSetHandler {" + NEW_LINE);
        classDebug.append(field);
        classDebug.append(fieldSetter);
        classDebug.append(sb.toString());
        classDebug.append("}" + NEW_LINE + NEW_LINE);

        return cg;
    }


    private String getResultHandlerName(Class<? extends Dao> daoClass) {
        return daoClass.getName() + "$ResultHandler";
    }

    private String getResultHandlerSimpleName(Class<? extends Dao> daoClass) {
        return daoClass.getSimpleName() + "$ResultHandler";
    }

    private ClassGenerator createDaoImplClass0(StringBuilder classDebug, Class<? extends Dao> daoClass, Class entityClass, Class idClass, TableDef table, String queueKey) {

        ClassGenerator cg = ClassGenerator.newInstance();
        cg.importPackage("java.sql");
        cg.importPackage("java.util");
        cg.importPackage("com.rtsapp.server.domain.mysql.sql");
        cg.importPackage("com.rtsapp.server.domain");
        cg.importPackage(entityClass.getPackage().getName());

        cg.setClassName(daoClass.getName() + "$Impl");
        cg.setSuperClass(daoClass);

        classDebug.append("public class " + daoClass.getSimpleName() + "$Impl extends " + daoClass.getName() + "{" + NEW_LINE);

        StringBuilder presqlBuilder = new StringBuilder();
        presqlBuilder.append("    public boolean innerPrepareStatement(com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db) {" + NEW_LINE);

        Method[] ms = daoClass.getMethods();
        for (Method m : ms) {
            String code = createMethodCode(daoClass, entityClass, idClass, table, cg, presqlBuilder, m, queueKey);

            if (code != null) {
                cg.addMethod(code);
                classDebug.append(code);
            }
        }
        presqlBuilder.append("        return true;" + NEW_LINE);
        presqlBuilder.append("    }" + NEW_LINE);

        cg.addMethod(presqlBuilder.toString());
        classDebug.append(presqlBuilder.toString());

        classDebug.append("}");

        if (log.isDebugEnabled()) {
            log.debug("创建Dao的子类" + classDebug.toString());
        }

        cg.addDefaultConstructor();

        return cg;
    }

    private String createMethodCode(Class<? extends Dao> daoClass, Class entityClass, Class idClass, TableDef table, ClassGenerator cg, StringBuilder presqlBuilder, Method m, String queueKey) {
        //实现抽象的dao方法
        if (Modifier.isAbstract(m.getModifiers())) {
            if (isInsertMethod(m, entityClass, idClass)) {
                return createInsert(false, cg, m, table, presqlBuilder, queueKey);
            } else if (isUpdateMethod(m, entityClass, idClass)) {
                return createUpdate(false, cg, m, table, presqlBuilder, queueKey);
            } else if (isDeleteMethod(m, entityClass, idClass)) {
                return createDelete(false, cg, m, table, presqlBuilder, queueKey);
            }

            if (isDirectInsertMethod(m, entityClass, idClass)) {
                return createInsert(true, cg, m, table, presqlBuilder, queueKey);
            } else if (isDirectUpdateMethod(m, entityClass, idClass)) {
                return createUpdate(true, cg, m, table, presqlBuilder, queueKey);
            } else if (isDirectDeleteMethod(m, entityClass, idClass)) {
                return createDelete(true, cg, m, table, presqlBuilder, queueKey);
            } else if (isGetAllMethod(m, entityClass, idClass)) {
                return createGetAll(daoClass, cg, m, table, presqlBuilder);
            } else if (isGetByMethod(m, entityClass, idClass)) {
                return createGetBy(daoClass, cg, m, table, presqlBuilder);
            } else if (isGetMethod(m, entityClass, idClass)) {
                return createGet(daoClass, cg, m, table, presqlBuilder);
            } else if (isUpdateForMethod(m, entityClass, idClass)) {
                return createUpdateFor(cg, m, table, presqlBuilder, queueKey);
            }
        }
        return null;
    }


    private boolean isInsertMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(INSERT) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }

    private boolean isUpdateMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(UPDATE) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }


    private boolean isDeleteMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(DELETE) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }


    private boolean isDirectInsertMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(DIRECT_INSERT) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }

    private boolean isDirectUpdateMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(DIRECT_UPDATE) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }


    private boolean isDirectDeleteMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(DIRECT_DELETE) && m.getParameterCount() == 1 && m.getParameterTypes()[0] == entityClass;
    }


    private boolean isGetAllMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(GETALL) && m.getParameterCount() == 0;
    }

    private boolean isGetMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().equalsIgnoreCase(GET) && m.getParameterCount() == 1;
    }

    private boolean isGetByMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        return m.getName().startsWith(GET_BY) && m.getParameterCount() >= 1;
    }


    private boolean isUpdateForMethod(Method m, Class<?> entityClass, Class<?> idClass) {
        if (m.getName().startsWith(UPDATE_FOR)) {
            return true;
        }
        return false;
    }

    /**
     * 根据队列key和表返回队列key字段
     *
     * @param queueKey
     * @param table
     * @return
     */
    private String getQueueField(String queueKey, TableDef table) {
        ColumnDef keyColumn;
        String[] queueKeys = queueKey.split("\\.");
        String queueField = "";
        if (queueKeys.length < 2) {
            keyColumn = table.getColumnByFieldName(queueKey);
            queueField += ("." + keyColumn.getGetterString());
        } else {
            TableDef keyTable = table;
            for (int i = 0; i < queueKeys.length; i++) {
                String queueKeysItem = queueKeys[i];
                keyColumn = keyTable.getColumnByFieldName(queueKeysItem);
                if (i < queueKeys.length - 1) {
                    queueField += ("." + keyColumn.getObjectGetterString());
                    try {
                        keyTable = JpaUtils.getTableDef(Class.forName(keyColumn.getFieldType()));
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                } else {
                    queueField += ("." + keyColumn.getGetterString());
                }
            }
        }
        return queueField;
    }

    private String createInsert(boolean isDirect, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder, String queueKey) {

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        StringBuilder insertSqlBuilder = new StringBuilder();
        insertSqlBuilder.append("insert into " + table.getTableName() + "( ");
        for (int i = 0; i < table.getColumns().size(); i++) {
            ColumnDef columnDef = table.getColumns().get(i);
            if (i > 0) {
                insertSqlBuilder.append(",");
            }
            insertSqlBuilder.append(columnDef.getColumnName());
        }
        insertSqlBuilder.append(" ) values ( ");
        for (int i = 0; i < table.getColumns().size(); i++) {
            if (i > 0) {
                insertSqlBuilder.append(",");
            }
            insertSqlBuilder.append("?");
        }
        insertSqlBuilder.append(" )");

        presqlBuilder.append("        if (!db.prepareStatement( " + PREPARE_SQL_NAME + ", \"" + insertSqlBuilder.toString() + " \")) {" + NEW_LINE + "            return false;" + NEW_LINE + "        } " + NEW_LINE);


        //2. sql执行代码
        StringBuilder insertParamsBuilder = new StringBuilder();
        String entityObj = "entity";
        for (int i = 0; i < table.getColumns().size(); i++) {
            ColumnDef columnDef = table.getColumns().get(i);
            if (i > 0) {
                insertParamsBuilder.append(", " + NEW_LINE);
            }
            insertParamsBuilder.append("                " + entityObj + "." + columnDef.getGetterString());
        }


        StringBuilder sb = new StringBuilder();
        ReflectUtils.getDesc(m);
        if (isDirect) {
            sb.append("    public boolean ");
        } else {
            sb.append("    public void ");
        }
        sb.append(m.getName() + "(" + m.getParameterTypes()[0].getName() + " entity) {");
        sb.append(NEW_LINE);

        //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
        sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getWritePool(); " + NEW_LINE);
        sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement(" + PREPARE_SQL_NAME + "); " + NEW_LINE);
        sb.append("        stmt.setParams(new Object[]{" + NEW_LINE + insertParamsBuilder.toString() + NEW_LINE + "        }); " + NEW_LINE);
        if (isDirect) {
            sb.append("        return db.directExecute(stmt);" + NEW_LINE);
        } else {
            if (queueKey != null) {

                sb.append("        db.execute(stmt, entity" + getQueueField(queueKey, table) + ");" + NEW_LINE);
            } else {
                sb.append("        db.execute(stmt);" + NEW_LINE);
            }
        }
        sb.append(NEW_LINE);
        sb.append("}" + NEW_LINE);
        return sb.toString();

    }

    private String createUpdate(boolean isDirect, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder, String queueKey) {


        ColumnDef[] columnDefs = new ColumnDef[table.getColumns().size()];
        table.getColumns().toArray(columnDefs);


        return createUpdateByColumns(isDirect, m, table, presqlBuilder, columnDefs, queueKey);

    }


    private String createDelete(boolean isDirect, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder, String queueKey) {

        String entityObj = "entity";

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        {
            StringBuilder deletePresqlBuilder = new StringBuilder();

            ColumnDef idColumn = table.getId();
            deletePresqlBuilder.append(" delete from  " + table.getTableName() + " where " + idColumn.getColumnName() + "= ? ");

            presqlBuilder.append("        if (!db.prepareStatement(" + PREPARE_SQL_NAME + ", \"" + deletePresqlBuilder.toString() + "\" )) {" + NEW_LINE + "            return false;" + NEW_LINE + "        } " + NEW_LINE);
        }

        //2. sql执行代码
        {
            ColumnDef idColumn = table.getId();

            StringBuilder sb = new StringBuilder();
            ReflectUtils.getDesc(m);
            if (isDirect) {
                sb.append("    public boolean ");
            } else {
                sb.append("    public void ");
            }
            sb.append(m.getName() + "(" + m.getParameterTypes()[0].getName() + " entity) {");
            sb.append(NEW_LINE);

            //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
            sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getWritePool(); " + NEW_LINE);
            sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + "); " + NEW_LINE);
            sb.append("        stmt.setParams(new Object[]{" + entityObj + "." + idColumn.getGetterString() + "}); " + NEW_LINE);
            if (isDirect) {
                sb.append("        return db.directExecute( stmt );" + NEW_LINE);
            } else {
                if (queueKey != null) {
                    sb.append("        db.execute( stmt, entity" + getQueueField(queueKey, table) + " );" + NEW_LINE);
                } else {
                    sb.append("        db.execute( stmt );" + NEW_LINE);
                }
            }
            sb.append(NEW_LINE);
            sb.append("    }" + NEW_LINE);
            return sb.toString();
        }
    }


    private String createGet(Class<? extends Dao> daoClass, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder) {

        String entityObj = "entity";

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        {
            StringBuilder getPresqlBuilder = new StringBuilder();
            getPresqlBuilder.append(" select ");

            int index = 0;
            for (ColumnDef columnDef : table.getColumns()) {
                if (index > 0) {
                    getPresqlBuilder.append(", ");
                }
                getPresqlBuilder.append(columnDef.getColumnName());

                index++;
            }

            ColumnDef idColumn = table.getId();
            getPresqlBuilder.append(" from " + table.getTableName() + " where " + idColumn.getColumnName() + "= ? ");
            presqlBuilder.append("        if (!db.prepareStatement( " + PREPARE_SQL_NAME + ", \"" + getPresqlBuilder.toString() + "\" ) ) {" + NEW_LINE + "            return false;" + NEW_LINE + "        } " + NEW_LINE);
        }

        //2. sql执行代码
        {
            StringBuilder getParamsBuilder = new StringBuilder();
            ColumnDef idColumn = table.getId();
            getParamsBuilder.append(" " + entityObj + ".get" + StringUtils.upperFirstChar(idColumn.getColumnName()) + "( )");

            StringBuilder sb = new StringBuilder();
            ReflectUtils.getDesc(m);
            sb.append("    public " + m.getReturnType().getName() + " " + m.getName() + "( " + m.getParameterTypes()[0].getName() + " id ){");
            sb.append(NEW_LINE);

            //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
            sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getReadPool(  ); " + NEW_LINE);
            sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + " ); " + NEW_LINE);
            sb.append("        stmt.setParams( new Object[]{ id } ); " + NEW_LINE);

            String handlerName = getResultHandlerSimpleName(daoClass);
            sb.append(handlerName + "  handler = new " + handlerName + "(); " + NEW_LINE);
            sb.append("        db.query( stmt, handler );" + NEW_LINE);

            sb.append("        if (handler.getEntityList().size() < 1 ){ return null; }else{" + NEW_LINE);
            sb.append("            return (" + m.getReturnType().getName() + ")( handler.getEntityList().get( 0 ) );" + NEW_LINE);
            sb.append("        } " + NEW_LINE);
            sb.append("    }" + NEW_LINE + NEW_LINE);

            return sb.toString();
        }
    }


    private String createGetBy(Class<? extends Dao> daoClass, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder) {


        String fieldNames = m.getName().replace(GET_BY, "");
        String[] columnNames = fieldNames.split("_");


        ColumnDef[] columnDefs = new ColumnDef[columnNames.length];
        for (int i = 0; i < columnDefs.length; i++) {
            columnDefs[i] = table.getColumnByFieldName(columnNames[i]);
        }

        String entityObj = "entity";

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        {
            StringBuilder getPresqlBuilder = new StringBuilder();
            getPresqlBuilder.append(" select ");

            int index = 0;
            for (ColumnDef columnDef : table.getColumns()) {
                if (index > 0) {
                    getPresqlBuilder.append(", ");
                }
                getPresqlBuilder.append(columnDef.getColumnName());

                index++;
            }

            getPresqlBuilder.append(" from " + table.getTableName() + " ");
            if (columnDefs.length > 0) {
                getPresqlBuilder.append(" where ");
                for (int i = 0; i < columnDefs.length; i++) {
                    if (i > 0) {
                        getPresqlBuilder.append(" and ");
                    }
                    getPresqlBuilder.append(columnDefs[i].getColumnName() + "= ? ");
                }
            }
            presqlBuilder.append("        if (!db.prepareStatement(" + PREPARE_SQL_NAME + ", \"" + getPresqlBuilder.toString() + "\")){" + NEW_LINE + "            return false;" + NEW_LINE + "        }" + NEW_LINE);
        }

        Class[] parameters = m.getParameterTypes();

        //2. sql执行代码
        {
            StringBuilder getParamsBuilder = new StringBuilder();
            ColumnDef idColumn = table.getId();
            getParamsBuilder.append(" " + entityObj + ".get" + StringUtils.upperFirstChar(idColumn.getColumnName()) + "( )");

            StringBuilder sb = new StringBuilder();
            ReflectUtils.getDesc(m);
            sb.append("    public " + m.getReturnType().getName() + " " + m.getName() + "(");

            for (int i = 0; i < parameters.length; i++) {
                if (i > 0) {
                    sb.append(", ");
                }
                sb.append(getTypeName(parameters[i]) + " p" + i);
            }

            sb.append(") {" + NEW_LINE);

            //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
            sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getReadPool(  ); " + NEW_LINE);
            sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + " ); " + NEW_LINE);
            sb.append("        stmt.setParams(new Object[]{" + NEW_LINE);


            for (int i = 0; i < parameters.length; i++) {
                if (i > 0) {
                    sb.append(", " + NEW_LINE);
                }
                sb.append("                p" + i);
            }

//            for( int i = 0; i < columnDefs.length; i++ ){
//                if (i >0 ){
//                    sb.append( "," );
//                }
//                sb.append( entityObj + "." + columnDefs[ i ].getGetterString() );
//            }

            sb.append(NEW_LINE + "        }); " + NEW_LINE);

            String handlerName = getResultHandlerSimpleName(daoClass);
            sb.append("        " + handlerName + " handler = new " + handlerName + "(); " + NEW_LINE);
            sb.append("        db.query(stmt, handler);" + NEW_LINE);
            if (m.getReturnType().isAssignableFrom(java.util.List.class)) {
                sb.append("        return (" + m.getReturnType().getName() + ")( handler.getEntityList() );" + NEW_LINE);
            } else {
                sb.append("        if (handler.getEntityList().size( ) > 0 ){" + NEW_LINE);
                sb.append("            return (" + m.getReturnType().getName() + ") (handler.getEntityList().get(0));" + NEW_LINE);
                sb.append("        } else {" + NEW_LINE);
                sb.append("            return null;" + NEW_LINE);
                sb.append("        }" + NEW_LINE);


            }
            sb.append("    }" + NEW_LINE + NEW_LINE);

            return sb.toString();
        }
    }


    private String getTypeName(Class clz) {
        return ReflectionUtils.getTypeName(clz);
    }


    private String createGetAll(Class<? extends Dao> daoClass, ClassGenerator cg, Method m, TableDef table, StringBuilder presqlBuilder) {

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        {
            StringBuilder getPresqlBuilder = new StringBuilder();
            getPresqlBuilder.append(" select ");

            int index = 0;
            for (ColumnDef columnDef : table.getColumns()) {
                if (index > 0) {
                    getPresqlBuilder.append(", ");
                }
                getPresqlBuilder.append(columnDef.getColumnName());

                index++;
            }

            getPresqlBuilder.append(" from " + table.getTableName());
            presqlBuilder.append("        if (!db.prepareStatement(" + PREPARE_SQL_NAME + ", \"" + getPresqlBuilder.toString() + "\")){" + NEW_LINE + "            return false;" + NEW_LINE + "        }" + NEW_LINE);
        }

        //2. sql执行代码
        {
            StringBuilder sb = new StringBuilder();
            ReflectUtils.getDesc(m);
            sb.append("    public " + m.getReturnType().getName() + " " + m.getName() + "() {");
            sb.append(NEW_LINE);


            sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getReadPool(); " + NEW_LINE);
            sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + " ); " + NEW_LINE);
            String handlerName = getResultHandlerSimpleName(daoClass);
            sb.append(handlerName + "  handler = new " + handlerName + "(); " + NEW_LINE);
            sb.append("        db.query( stmt, handler );" + NEW_LINE);

            sb.append("        return handler.getEntityList();" + NEW_LINE);

            sb.append("    }" + NEW_LINE);


            //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
//            sb.append("    com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getReadPool(  ); " + NEW_LINE);
//            sb.append(" MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + " ); " + NEW_LINE);
//            sb.append(" final ArrayList<" +  table.getEntityName() +  "> entityList = new ArrayList<>(); " + NEW_LINE );
//            sb.append(" db.query( stmt, new  MySQLResultSetHandler() { " + NEW_LINE);
//            sb.append(" public void doResultSet(ResultSet rs) {"  + NEW_LINE );
//            sb.append(" try{ "  + NEW_LINE);
//            sb.append("   while( rs.next() ) {"  + NEW_LINE );
//
//                    sb.append(" " +  table.getEntityName() +  " entity = EntityBuilder.newEntity( " +  table.getEntityName() + ".class );" + NEW_LINE );
//                    createGetOnEntityCode(table, sb);
//                    sb.append( "entity.clearDirty();"  + NEW_LINE );
//            sb.append("entityList.add( entity );" + NEW_LINE );
//
//            sb.append("   }"  + NEW_LINE );
//            sb.append( "} catch (SQLException e) {" + NEW_LINE );
//            sb.append( "    e.printStackTrace();" + NEW_LINE );
//            sb.append(" }" + NEW_LINE );
//            sb.append(" }" + NEW_LINE );
//            sb.append(" });" + NEW_LINE );
//            sb.append( " return entityList;" + NEW_LINE );
//            sb.append( " } " + NEW_LINE );


            return sb.toString();
        }
    }


    private String createUpdateFor(ClassGenerator cg, Method m, TableDef tableDef, StringBuilder presqlBuilder, String queueKey) {

        String entityObj = "entity";

        String fieldNames = m.getName().replace(UPDATE_FOR, "");
        String[] columnNames = fieldNames.split("_");

        ColumnDef[] columnDefs = new ColumnDef[columnNames.length];
        for (int i = 0; i < columnDefs.length; i++) {
            columnDefs[i] = tableDef.getColumnByFieldName(columnNames[i]);
        }

        return createUpdateByColumns(false, m, tableDef, presqlBuilder, columnDefs, queueKey);


    }


    private void createGetOnEntityCode(TableDef table, StringBuilder sb) {
        for (int i = 0; i < table.getColumns().size(); i++) {
            ColumnDef columnDef = table.getColumns().get(i);
            //TODO  joincolumn现在没有赋值
            if (columnDef.isJoinColumn()) {
                sb.append("                rs.getObject(" + (i + 1) + ");" + NEW_LINE);
            } else {
                String castType = "";
                if (columnDef.getFieldType().equals("java.lang.Byte")) {
                    castType = "Byte.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Short")) {
                    castType = "Short.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Integer")) {
                    castType = "Integer.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Long")) {
                    castType = "Long.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Float")) {
                    castType = "Float.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Double")) {
                    castType = "Double.valueOf";
                } else if (columnDef.getFieldType().equals("java.lang.Boolean")) {
                    castType = "Boolean.valueOf";
                }

                sb.append("                entity.set" + StringUtils.upperFirstChar(columnDef.getFieldName()) + "(" + castType + "(rs.get" + StringUtils.upperFirstChar(JpaUtils.getSqlMappingType(columnDef.getFieldType())) + "(" + (i + 1) + ")));" + NEW_LINE);
            }
        }
    }


    private String createUpdateByColumns(boolean isDirect, Method m, TableDef table, StringBuilder presqlBuilder, ColumnDef[] columnDefs, String queueKey) {
        String entityObj = "entity";

        //1. presql预编译代码
        String PREPARE_SQL_NAME = getSqlName(m);

        {
            StringBuilder updatePresqlBuilder = new StringBuilder();
            updatePresqlBuilder.append("update " + table.getTableName() + " set ");

            int index = 0;
            for (ColumnDef columnDef : columnDefs) {
                if (!table.isIdColumn(columnDef)) {
                    if (index > 0) {
                        updatePresqlBuilder.append(", ");
                    }

                    updatePresqlBuilder.append(columnDef.getColumnName() + "=? ");

                    index++;
                }
            }
            ColumnDef idColumn = table.getId();
            updatePresqlBuilder.append(" where " + idColumn.getColumnName() + "= ? ");
            presqlBuilder.append("        if (!db.prepareStatement(" + PREPARE_SQL_NAME + ",\" " + updatePresqlBuilder.toString() + "\")){" + NEW_LINE + "            return false;" + NEW_LINE + "        }" + NEW_LINE);
        }

        //2. sql执行代码
        {
            StringBuilder updateParamsBuilder = new StringBuilder();
            int index = 0;
            for (ColumnDef columnDef : columnDefs) {
                if (!table.isIdColumn(columnDef)) {
                    if (index > 0) {
                        updateParamsBuilder.append(", " + NEW_LINE);
                    }
                    updateParamsBuilder.append("                " + entityObj + "." + columnDef.getGetterString());
                    index++;
                }
            }
            ColumnDef idColumn = table.getId();
            updateParamsBuilder.append(", " + NEW_LINE + "                " + entityObj + "." + idColumn.getGetterString());

            StringBuilder sb = new StringBuilder();
            ReflectUtils.getDesc(m);
            if (isDirect) {
                sb.append("    public boolean ");
            } else {
                sb.append("    public void ");
            }
            sb.append(m.getName() + "( " + m.getParameterTypes()[0].getName() + " entity ){");
            sb.append(NEW_LINE);

            //获得workpool, 获得预编译sql语句, 设置参数, 执行预编译sql语句
            sb.append("        com.rtsapp.server.domain.mysql.sql.DatabaseWorkerPool db = getWritePool(  ); " + NEW_LINE);
            sb.append("        MySQLPreparedStatement stmt =  db.getPreparedStatement( " + PREPARE_SQL_NAME + " ); " + NEW_LINE);
            sb.append("        stmt.setParams( new Object[]{" + NEW_LINE + updateParamsBuilder.toString() + NEW_LINE + "        }); " + NEW_LINE);

            if (isDirect) {
                sb.append("        return db.directExecute( stmt );" + NEW_LINE);
            } else {
                if (queueKey != null) {
                    sb.append("        db.execute( stmt, entity" + getQueueField(queueKey, table) + " );" + NEW_LINE);
                } else {
                    sb.append("        db.execute( stmt );" + NEW_LINE);
                }
            }

            sb.append("    }" + NEW_LINE);
            return sb.toString();
        }
    }

    private String getSqlName(Method m) {
        StringBuilder sb = new StringBuilder();
        sb.append("\"");
        sb.append(m.getDeclaringClass().getSimpleName() + "_" + m.getName());
        for (Class<?> paramType : m.getParameterTypes()) {
            sb.append("_" + paramType.getSimpleName());
        }
        sb.append("\"");
        return sb.toString();
    }


}
